{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:516: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:517: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:518: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:519: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:520: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\python\\framework\\dtypes.py:525: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorboard\\compat\\tensorflow_stub\\dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorboard\\compat\\tensorflow_stub\\dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorboard\\compat\\tensorflow_stub\\dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorboard\\compat\\tensorflow_stub\\dtypes.py:544: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorboard\\compat\\tensorflow_stub\\dtypes.py:545: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorboard\\compat\\tensorflow_stub\\dtypes.py:550: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "from matplotlib import pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "tf.logging.set_verbosity(tf.logging.INFO)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From <ipython-input-2-1966de352905>:2: read_data_sets (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use alternatives such as official/mnist/dataset.py from tensorflow/models.\n",
      "WARNING:tensorflow:From E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:260: maybe_download (from tensorflow.contrib.learn.python.learn.datasets.base) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please write your own downloading logic.\n",
      "WARNING:tensorflow:From E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:262: extract_images (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.data to implement this functionality.\n",
      "Extracting ./train-images-idx3-ubyte.gz\n",
      "WARNING:tensorflow:From E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:267: extract_labels (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.data to implement this functionality.\n",
      "Extracting ./train-labels-idx1-ubyte.gz\n",
      "WARNING:tensorflow:From E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:110: dense_to_one_hot (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.one_hot on tensors.\n",
      "Extracting ./t10k-images-idx3-ubyte.gz\n",
      "Extracting ./t10k-labels-idx1-ubyte.gz\n",
      "WARNING:tensorflow:From E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:290: DataSet.__init__ (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use alternatives such as official/mnist/dataset.py from tensorflow/models.\n",
      "(55000, 784)\n",
      "(55000, 10)\n",
      "(5000, 784)\n",
      "(5000, 10)\n",
      "(10000, 784)\n",
      "(10000, 10)\n"
     ]
    }
   ],
   "source": [
    "# 数据下载\n",
    "mnist = input_data.read_data_sets(\"./\", one_hot=True)\n",
    "\n",
    "print(mnist.train.images.shape)\n",
    "print(mnist.train.labels.shape)\n",
    "\n",
    "print(mnist.validation.images.shape)\n",
    "print(mnist.validation.labels.shape)\n",
    "\n",
    "print(mnist.test.images.shape)\n",
    "print(mnist.test.labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x576 with 16 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 设置每张图片的大小,表示figure的大小为宽/长(单位为inch)\n",
    "plt.figure(figsize=(8, 8))\n",
    "# 显示测试图片\n",
    "for idx in range(16):\n",
    "    # (4行, 4列, 第idx+1张图片)\n",
    "    plt.subplot(4, 4, idx + 1)\n",
    "    plt.axis('off')\n",
    "    plt.title('[{}]'.format(np.argmax(mnist.train.labels[idx])))\n",
    "    plt.imshow(mnist.train.images[idx].reshape((28, 28)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "    定义所有操作(均为计算图),即:定义神经网络的结构\n",
    "\"\"\"\n",
    "# 定义两个placeholder分别用于图像和lable数据\n",
    "x = tf.placeholder(\"float\", [None, 784], name='x')\n",
    "y = tf.placeholder(\"float\", [None, 10], name='y')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "    数据x转成4维tensor[batch, in_height, in_width, in_channels]结构\n",
    "    \n",
    "    -1:第一维度大小待定\n",
    "\"\"\"\n",
    "x_image = tf.reshape(x, [-1, 28, 28, 1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "    第一个卷积层:\n",
    "        使用6个5X5的卷积核对输入数据进行卷积(卷积6次,识别6种特征)\n",
    "        padding方式选择valid,输出数据的宽高变为24x24,但是深度已经从原来的1变成了6。 \n",
    "        卷积的激活函数为relu\n",
    "\"\"\"\n",
    "with tf.name_scope('conv1'):\n",
    "    C1 = tf.contrib.slim.conv2d(x_image, 6, [5, 5], padding='VALID', activation_fn=tf.nn.relu)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "    进行stride=2的最大池化:\n",
    "        池化后,输出深度不变,长宽减半(输出变成了12x12,深度6)\n",
    "\"\"\"\n",
    "with tf.name_scope('pool1'):\n",
    "    S2 = tf.contrib.slim.max_pool2d(C1, [2, 2], stride=[2, 2], padding='VALID')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "    第二个卷积层:\n",
    "        使用16个5X5的卷积核对输入数据进行卷积\n",
    "        padding方式还是选择valid,输出8x8,深度为16\n",
    "        卷积的激活函数为relu\n",
    "\"\"\"\n",
    "with tf.name_scope('conv2'):\n",
    "    C3 = tf.contrib.slim.conv2d(\n",
    "        S2, 16, [5, 5], padding='VALID', activation_fn=tf.nn.relu)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "    进行stride=2的最大池化:\n",
    "        输出为4x4,深度16\n",
    "\"\"\"\n",
    "with tf.name_scope('pool2'):\n",
    "    S4 = tf.contrib.slim.max_pool2d(C3, [2, 2], stride=[2, 2], padding='VALID')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\contrib\\layers\\python\\layers\\layers.py:1634: flatten (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.flatten instead.\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "    池化后的数据是3维的,这里做一个拉平的操作,将3维数据展开到1维,\n",
    "    然后送入两层全连接,全连接隐层中神经元个数分别为120，84\n",
    "\"\"\"\n",
    "with tf.name_scope('fc1'):\n",
    "    S4_flat = tf.contrib.slim.flatten(S4)\n",
    "    C5 = tf.contrib.slim.fully_connected(S4_flat, 120, activation_fn=tf.nn.relu)\n",
    "\n",
    "with tf.name_scope('fc2'):\n",
    "    F6 = tf.contrib.slim.fully_connected(C5, 84, activation_fn=tf.nn.relu)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From <ipython-input-11-dde072d3343e>:9: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "    对特征添加一个0.6的dropout,以40%的概率丢弃特征中的某些数据,提高网络推广能力,减少过拟合。\n",
    "    注意:\n",
    "        dropout仅在训练的时候使用,验证时,需要关闭dropout,所以验证时的keep_prob是1.0。\n",
    "        dropout的输出最终送入一个隐层为10的全连接层,这个全连接层即为最后的分类器。\n",
    "\"\"\"\n",
    "with tf.name_scope('dropout'):\n",
    "    keep_prob = tf.placeholder(name='keep_prob', dtype=tf.float32)\n",
    "    F6_drop = tf.nn.dropout(F6, keep_prob)\n",
    "    \n",
    "# 最后输出的是未经softmax的原始logits\n",
    "with tf.name_scope('fc3'):\n",
    "    logits = tf.contrib.slim.fully_connected(F6_drop, 10, activation_fn=None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Conv/weights:0\n",
      "INFO:tensorflow:Summary name Conv/weights:0 is illegal; using Conv/weights_0 instead.\n",
      "Conv/biases:0\n",
      "INFO:tensorflow:Summary name Conv/biases:0 is illegal; using Conv/biases_0 instead.\n",
      "Conv_1/weights:0\n",
      "INFO:tensorflow:Summary name Conv_1/weights:0 is illegal; using Conv_1/weights_0 instead.\n",
      "Conv_1/biases:0\n",
      "INFO:tensorflow:Summary name Conv_1/biases:0 is illegal; using Conv_1/biases_0 instead.\n",
      "fully_connected/weights:0\n",
      "INFO:tensorflow:Summary name fully_connected/weights:0 is illegal; using fully_connected/weights_0 instead.\n",
      "fully_connected/biases:0\n",
      "INFO:tensorflow:Summary name fully_connected/biases:0 is illegal; using fully_connected/biases_0 instead.\n",
      "fully_connected_1/weights:0\n",
      "INFO:tensorflow:Summary name fully_connected_1/weights:0 is illegal; using fully_connected_1/weights_0 instead.\n",
      "fully_connected_1/biases:0\n",
      "INFO:tensorflow:Summary name fully_connected_1/biases:0 is illegal; using fully_connected_1/biases_0 instead.\n",
      "fully_connected_2/weights:0\n",
      "INFO:tensorflow:Summary name fully_connected_2/weights:0 is illegal; using fully_connected_2/weights_0 instead.\n",
      "fully_connected_2/biases:0\n",
      "INFO:tensorflow:Summary name fully_connected_2/biases:0 is illegal; using fully_connected_2/biases_0 instead.\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "    定义loss和网络优化器:\n",
    "        loss计算使用了sparse_softmax_cross_entropy_with_logits, \n",
    "        这样做的好处是labels可以不用手动做one_hot省了一些麻烦。这里使用了sgd优化器，学习率为0.3   \n",
    "\"\"\"\n",
    "# 损失计算\n",
    "cross_entropy_loss = tf.reduce_mean(\n",
    "    tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=y))\n",
    "\n",
    "l2_loss = tf.add_n([\n",
    "    tf.nn.l2_loss(w)\n",
    "    for w in tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES)\n",
    "])\n",
    "\n",
    "for w in tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES):\n",
    "    print(w.name)\n",
    "    tf.summary.histogram(w.name, w)\n",
    "    \n",
    "total_loss = cross_entropy_loss + 7e-5 * l2_loss\n",
    "tf.summary.scalar('cross_entropy_loss', cross_entropy_loss)\n",
    "tf.summary.scalar('l2_loss', l2_loss)\n",
    "tf.summary.scalar('total_loss', total_loss)\n",
    "\n",
    "optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.3).minimize(total_loss)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "    将输出的结果与正确结果进行对比，即可得到我们的网络输出结果的准确率\n",
    "\"\"\"\n",
    "pred = tf.nn.softmax(logits)\n",
    "correct_pred = tf.equal(tf.argmax(y, 1), tf.argmax(logits, 1))\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "batch_size = 100\n",
    "trainig_step = 1100\n",
    "\n",
    "# saver保存或恢复训练的模型\n",
    "saver = tf.train.Saver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "after 100 training steps, the loss is 0.390105, the validation accuracy is 0.9174\n",
      "after 200 training steps, the loss is 0.151613, the validation accuracy is 0.955\n",
      "after 300 training steps, the loss is 0.246062, the validation accuracy is 0.9686\n",
      "after 400 training steps, the loss is 0.120221, the validation accuracy is 0.9716\n",
      "after 500 training steps, the loss is 0.121559, the validation accuracy is 0.9692\n",
      "after 600 training steps, the loss is 0.0791322, the validation accuracy is 0.9788\n",
      "WARNING:tensorflow:From E:\\anaconda3\\envs\\tf1.14\\lib\\site-packages\\tensorflow\\python\\training\\saver.py:960: remove_checkpoint (from tensorflow.python.training.checkpoint_management) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use standard file APIs to delete files with this prefix.\n",
      "after 700 training steps, the loss is 0.0302702, the validation accuracy is 0.9828\n",
      "after 800 training steps, the loss is 0.024452, the validation accuracy is 0.981\n",
      "after 900 training steps, the loss is 0.0800389, the validation accuracy is 0.9798\n",
      "after 1000 training steps, the loss is 0.139029, the validation accuracy is 0.9822\n",
      "the training is finish!\n",
      "the test accuarcy is: 0.9823\n"
     ]
    }
   ],
   "source": [
    "merged = tf.summary.merge_all()\n",
    "with tf.Session() as sess:\n",
    "    # 计算图存储到logs(断点恢复从跑)\n",
    "    writer = tf.summary.FileWriter(\"logs/\", sess.graph)\n",
    "    \n",
    "    # sess全局变量初始化\n",
    "    sess.run(tf.global_variables_initializer())\n",
    "\n",
    "    #定义验证集\n",
    "    validate_data = {\n",
    "        x: mnist.validation.images,\n",
    "        y: mnist.validation.labels,\n",
    "        keep_prob: 1.0\n",
    "    }\n",
    "    \n",
    "    #定义测试集\n",
    "    test_data = {x: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0}\n",
    "\n",
    "    for i in range(trainig_step):\n",
    "        # 每次处理100张图片\n",
    "        xs, ys = mnist.train.next_batch(batch_size)\n",
    "        _, loss, rs = sess.run(\n",
    "            [optimizer, cross_entropy_loss, merged],\n",
    "            feed_dict={\n",
    "                x: xs,\n",
    "                y: ys,\n",
    "                keep_prob: 0.6\n",
    "            })\n",
    "        writer.add_summary(rs, i)\n",
    "\n",
    "        #每100次训练打印一次损失值与验证准确率\n",
    "        if i > 0 and i % 100 == 0:\n",
    "            validate_accuracy = sess.run(accuracy, feed_dict=validate_data)\n",
    "            print(\"after %d training steps, the loss is %g, the validation accuracy is %g\"\n",
    "                % (i, loss, validate_accuracy))\n",
    "            saver.save(sess, './model.ckpt', global_step=i)\n",
    "\n",
    "    print(\"the training is finish!\")\n",
    "    #最终的测试准确率\n",
    "    acc = sess.run(accuracy, feed_dict=test_data)\n",
    "    print(\"the test accuarcy is:\", acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
